package utils

import (
	"fmt"
	"github.com/liuxd6825/dapr-ddd-cli/pkg/resource"
	"os"
	"strings"
	"text/template"
)

//
// RunTemplate
// @Description: 生成源代码文件
// @param tmplFile 模板文件
// @param data 模板数据
// @param outFile 输出文件名
// @param overwrite 是否覆盖现有文件，true:覆盖
// @return error
//
func RunTemplate(tmplFile string, data interface{}, outFile string, overwrite bool) error {
	bytes, err := resource.Local().ReadFile(tmplFile)
	if err != nil {
		return err
	}
	tmpl := template.New(tmplFile).Funcs(template.FuncMap{
		"runTemplate":    RunTemplate,
		"firstUpper":     FirstUpper,
		"firstLower":     FirstLower,
		"getData":        GetData,
		"add":            Add,
		"join":           Join,
		"braces":         Braces,
		"contains":       strings.Contains,
		"hasPrefix":      strings.HasPrefix,
		"hasSuffix":      strings.HasSuffix,
		"isNodeName":     isNodeName,
		"isRelationName": isRelationName,
		"isNeo4jName":    isNeo4jName,
		"snake":          SnakeString,
	})
	tmpl, err = tmpl.Parse(string(bytes))
	if err != nil {
		fmt.Println("template.Parse():", err)
		return err
	}

	w := os.Stdout
	defer func() {
		if w != os.Stdout {
			_ = w.Close()
		}
	}()

	if len(outFile) > 0 {
		dirName := GetDirName(outFile)
		if err = os.MkdirAll(dirName, os.ModePerm); err != nil {
			return err
		}

		// 如果不覆盖，并且文件存在，则退出
		if !overwrite && existsFile(outFile) {
			println("exists: " + outFile)
			return nil
		}

		if w, err = os.Create(outFile); err != nil {
			return err
		}
	}

	if err = tmpl.Execute(w, data); err != nil {
		return err
	} else {
		println("write: " + outFile)
	}
	return nil
}

// existsFile 文件是否存在
func existsFile(fileName string) bool {
	_, err := os.Stat(fileName) //os.Stat获取文件信息
	if err != nil {
		if os.IsExist(err) {
			return true
		}
		return false
	}
	return true
}

func GetData(dataMap map[string]interface{}) interface{} {
	if res, ok := dataMap["data"]; ok {
		return res
	}
	return nil
}

func GetDirName(fileName string) string {
	last := strings.LastIndex(fileName, "/")
	if last > -1 {
		return fileName[0:last]
	}
	last = strings.LastIndex(fileName, "\\")
	if last > -1 {
		return fileName[0:last]
	}
	return ""
}

func isNodeName(name string) bool {
	return strings.HasSuffix(name, "Node")
}

func isRelationName(name string) bool {
	if strings.HasSuffix(name, "Line") {
		return true
	} else if strings.HasSuffix(name, "Relation") {
		return true
	}
	return false
}

func isNeo4jName(name string) bool {
	return isNodeName(name) || isRelationName(name)
}
